﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using CommonBehaviors.Actions;
using Styx;
using Styx.Common;
using Styx.Pathing;
using Styx.TreeSharp;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Action = Styx.TreeSharp.Action;

namespace TSMBuddy
{
    public static class Helpers
    {
        public delegate WoWUnit UnitDelegate(object context);
        public delegate WoWGameObject GameObjectDelegate(object context);
        public delegate WoWPoint PointDelegate(object context);
        public delegate float FloatDelegate(object context);
        public delegate int IntDelegate(object context);
        public delegate bool BoolDelegate(object context);

        public static WoWUnit NearestAuctioneer
        {
            get { return ObjectManager.GetObjectsOfType<WoWUnit>().OrderBy(u => u.Distance).FirstOrDefault(u => u.IsAuctioneer); }
        }
        public static WoWGameObject NearestMailbox
        {
            get { return ObjectManager.GetObjectsOfType<WoWGameObject>().OrderBy(o => o.Distance).FirstOrDefault(o => o.SubType == WoWGameObjectType.Mailbox); }
        }
        public static WoWUnit NearestBanker
        {
            get { return ObjectManager.GetObjectsOfType<WoWUnit>().OrderBy(u => u.Distance).FirstOrDefault(u => u.IsBanker); }
        }
        public static WoWGameObject NearestGBank
        {
            get
            {
                var gbank = ObjectManager.GetObjectsOfType<WoWGameObject>().OrderBy(o => o.Distance).FirstOrDefault(o => o.SubType == WoWGameObjectType.GuildBank);
                return gbank;
            }
        }

        public static int CachedTakableMailCount;
        public static int TakableMailCount
        {
            get
            {
                var inbox = Styx.CommonBot.Frames.MailFrame.Instance.GetAllMails().Count(m => m.Copper > 0 || m.ItemCount > 0);
                return inbox;
            }
        }

        public static Composite GotoPoint(PointDelegate point, FloatDelegate range)
        {
            return new PrioritySelector(
                new Decorator(ret => point(ret).Distance(StyxWoW.Me.Location) <= range(ret), new ActionAlwaysSucceed()),
                new Sequence(
                    new DecoratorContinue(
                        ret => point(ret).Distance(StyxWoW.Me.Location) > range(ret),
                        new Action(ret => { Navigator.MoveTo(point(ret)); return RunStatus.Failure; })
                        ),
                    new Action(delegate { Navigator.Clear(); })
                    )
                );
        }

        public static Composite Wait(WaitGetTimeoutDelegate waitTime)
        {
            return new WaitContinue(waitTime, ret => false, new ActionAlwaysSucceed());
        }

        public static Composite GotoPoint(PointDelegate point)
        {
            return GotoPoint(point, range => 0);
        }
        public static Composite InteractWithUnit(UnitDelegate unit)
        {
            return new Sequence(
                new DecoratorContinue(ret => unit(ret).Distance > unit(ret).InteractRange, GotoPoint(ret => unit(ret).Location, ret => unit(ret).InteractRange)),
                new DecoratorContinue(ret => StyxWoW.Me.MovementInfo.IsMoving, new Action(delegate { WoWMovement.MoveStop(); })),
                new Sequence(
                    new Action(ret => unit(ret).Interact()),
                    new Wait(TimeSpan.FromMilliseconds(700), ret => false, new ActionAlwaysSucceed())
                    )
                );
        }
        public static Composite InteractWithObject(GameObjectDelegate wowObject)
        {
            return new Sequence(
                new DecoratorContinue(ret => wowObject(ret).Distance > wowObject(ret).InteractRange, GotoPoint(ret => wowObject(ret).Location, ret => wowObject(ret).InteractRange)),
                new DecoratorContinue(ret => StyxWoW.Me.MovementInfo.IsMoving, new Action(delegate { WoWMovement.MoveStop(); })),
                new Sequence(
                    new Action(ret => wowObject(ret).Interact()),
                    new Wait(TimeSpan.FromMilliseconds(700), ret => false, new ActionAlwaysSucceed())
                    )
                );
        }

        public static string AHTabByName(string wantedTab)
        {
            int i = 0;
            bool stoploop = false;

            string tab = null; 

            //Get all Auction House tabs
            do
            {
                i++;
                string tabName = Lua.GetReturnVal<string>("return AuctionFrameTab" + i.ToString() + ":GetText()", 0);
                if (tabName != null)
                {
                    if (tabName.Contains(wantedTab))
                    {
                        tab = "AuctionFrameTab" + i.ToString();
                    }
                }
                else
                {
                    stoploop = true;
                }
            }
            while (!stoploop);

            return tab;
        }

        public static bool checkScanComplete()
        {
            bool check = false;

            string btnText = Lua.GetReturnVal<string>("return TSMStopScanButton:GetText()", 0);

            //Lua.DoString("RunMacroText(\"/click TSMAuctioningCancelButton\")");

            if (btnText.Contains("Restart"))
            {
                Logging.Write("Scan Complete");
                check = true;
                TSMBuddy.scanComplete = true;
            }

            return check;
        }

        public enum States
        {
            CancelScan,
            GetMail,
            PostScan,
            waitCancelScanComplete,
            waitPostScanComplete,
            Wait,
            StopLoop
        }

    }
}
